package com.tongbu;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SynchronizedExample {

    /**
     * java 提供了 两种锁机制 来控制多个线程对共享资源的互斥访问，第一个是JVM 实现synchronized,而另一个是JDK实现的ReentrantLock
     */


    //同步一个代码块 ：只作用与同一个对象，如果调用两个对象上的同步代码块，就不会进行同步。
    public void func(){
        synchronized (this){
            System.out.println("okok");
        }
        synchronized (this){
            System.out.println("okok1111");
        }
    }

    public void func1(){
        synchronized (this){
            for(int i=0;i<10;i++){
                System.out.print(i+"  ");
            }
            System.out.println(" ");
        }
    }

    //同步一个方法
    public synchronized void func2(){
        System.out.println("同步一个方法");
    }

    //同步一个类  和同步代码块一样，作用于同一个对象。
    public void func3(){
            synchronized (SynchronizedExample.class)
            {
                System.out.println("func3 来了");
            }
    }


    //作用于整个类，也就是说两个线程调用同一个类的不同对象上的这种同步遇见，也会进行同步。
    public void func4(){
        synchronized (SynchronizedExample.class){
            for(int i=0;i<10;i++){
                System.out.print(i+" ");
            }
        }
    }



    //同步一个静态方法  作用于整个类
    public synchronized static void fun(){
        System.out.println("同步一个静态方法");
    }

    public static void main(String[] args) {
        SynchronizedExample SynchronizedExample =new SynchronizedExample();
        SynchronizedExample.func();
        SynchronizedExample.func1();


        System.out.println("-----------ExecutorService执行两个线程，调用的是同一个对象的同步代码块，因此这两个线程会进行同步，当一个线程进入同步语句块是，另一个线程就必须等待。------------");
        ExecutorService executorService= Executors.newCachedThreadPool();
        executorService.execute(() -> SynchronizedExample.func1());
        executorService.execute(() -> SynchronizedExample.func1());


        System.out.println("----两个线程调用不同对象的同步代码块，因此这两个线程不需要同步。两个线程交叉执行---");

        SynchronizedExample e2=new SynchronizedExample();
        executorService.execute(() -> SynchronizedExample.func1());
        executorService.execute(()->e2.func1());


        System.out.println("------------------------------------------");
        SynchronizedExample e3=new SynchronizedExample();
        SynchronizedExample e4=new SynchronizedExample();
        ExecutorService executorService2=Executors.newCachedThreadPool();
        executorService2.execute(()->e3.func4());
        executorService2.execute(()->e4.func4());



    }
}
